﻿using System;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Json;
using System.Text;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.Win32;
using NLog;
using NerdWare.Crm2011VsTools.Core;
using NerdWare.Crm2011VsTools.Globals;

namespace NerdWare.Crm2011VsTools.DialogPages
{
    [Guid(GuidList.GeneralOptionPage)]
    internal class GeneralOptionsPage : DialogPage
    {
        [Category(Category.CrmServer), DisplayName("Crm Servers"), Description("List of CRM connections")]
        public CrmServerConnection[] CRMServerConnections { get; set; }

        private int _fiddlerPort = 8899;

        [Category(Category.Fiddler)]
        [DisplayName("Fiddler Port")]
        [Description("The Port on which Fiddler should run. Usually it is 8899.")]
        public int FiddlerPort
        {
            get { return _fiddlerPort; }
            set { _fiddlerPort = value; }
        }

        private string _globalScriptFolder = @"c:\";

        [Category(Category.Fiddler)]
        [DisplayName("GlobalScriptFolder")]
        [Description("The Folder with the replacement files located.")]
        public string GlobalScriptFolder
        {
            get { return this._globalScriptFolder; }
            set { this._globalScriptFolder = value; }
        }

        private bool _logging;

        [Category(Category.Development)]
        [DisplayName("Logging Enabled")]
        [Description("Enables or disables the Logging.")]
        public bool Logging
        {
            get { return _logging; }
            set
            {
                _logging = value;
                if (_logging) { LogManager.EnableLogging(); }
                else { LogManager.DisableLogging(); }
            }
        }

        public override void LoadSettingsFromStorage()
        {
            base.LoadSettingsFromStorage();
            // Load the CrmConnections from Filesystem or Registry
            using (var key = OpenRegistry(false))
            {
                var json = (key != null) ? key.GetValue("CrmServerConnections") as string : null;
                CRMServerConnections = (string.IsNullOrEmpty(json) || json == "[]") ? DefaultConnections() : DeserializeConnectionSettings(json);
            }
        }

        public override void SaveSettingsToStorage()
        {
            base.SaveSettingsToStorage();

            using (var ms = new MemoryStream())
            {
                var serializer = new DataContractJsonSerializer(typeof(CrmServerConnection[]));
                serializer.WriteObject(ms, CRMServerConnections);
                var serializedString = Encoding.UTF8.GetString(ms.ToArray());
                using (var key = OpenRegistry(true))
                {
                    key.SetValue("CrmServerConnections", serializedString);
                }
            }
        }


        private static string _registryPath;
        private static string RegistryPath
        {
            get
            {
                return _registryPath ?? (_registryPath = string.Format(@"DialogPage\{0}", typeof(GeneralOptionsPage).FullName));
            }
        }

        private static RegistryKey OpenRegistry(bool writeable)
        {
            var root = VSRegistry.RegistryRoot(__VsLocalRegistryType.RegType_UserSettings, writeable);
            var subKey = writeable
                ? root.CreateSubKey(RegistryPath)
                : root.OpenSubKey(RegistryPath);
            return subKey;
        }

        private static CrmServerConnection[] DefaultConnections()
        {
            return new[]
                {
                    new CrmServerConnection {Server = "servername", Port = 5555, Type = CrmType.Crm2011OnPremise, Organization = "basicorg"}
                };
        }


        /// <summary>
        /// Deserializes the connection settings.
        /// </summary>
        /// <param name="serializedString">The serialized String.</param>
        /// <returns></returns>
        private static CrmServerConnection[] DeserializeConnectionSettings(string serializedString)
        {
            try
            {
                using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(serializedString)))
                {
                    var serializer = new DataContractJsonSerializer(typeof(CrmServerConnection[]));
                    var patterns = serializer.ReadObject(ms) as CrmServerConnection[];
                    return patterns ?? DefaultConnections();
                }
            }
            catch (Exception)
            {
                return DefaultConnections();
            }
        }
    }
}
